package org.flexitools.grapher;		

import java.util.HashSet;

import graph.Edge;
import graph.Graph;
import graph.Node;
import graph.TextGraphBuilder;
import graph.algorithm.Multiplyer;
import graph.algorithm.Rotator;
import graph.algorithm.Transformer;
import graph.layout.AutoLayout;
import graph.layout.CenterLayout;
import graph.layout.FlattenLayout;
import graph.layout.RandomLayout;
import graph.layout.ShakeLayout;
import graph.layout.Sphere2PlaneLayout;
import graph.layout.XYLayout;
import graph.paint.GraphPainter;
import graph.paint.ViewPort;
import graph.paint.text.GeoPainter;
import graph.paint.text.TextPainter;
import graph.property.PlaneGraphProperty;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {

	public static final String ID = "org.flexitools.grapher.view";
	static String[] graphs = {
		"a-b-c-d,c-e-f,g-e-h,i-j-h,k-j-l-m,l-n-o-p,l-q-r-l,s-r-t,r-u,q-v-w-x,w-y",
		"",
		"abba-boboo",
		"abba-boboo-cafe-dodo-elfenben-fobi-gnav-holekleiv,dodo-abba-holekleiv-elfenben,cafe-fobi,boboo-gnav",
		"0-1-2-0-3-4-0-5-6-0-7-8-0-9-8-80-90-9-1-10-20-2-3-30-40-4-5-50-60-6-7-70-80,10-90,20-30,40-50,60-70",
	};
	static int index=1;
	static ViewPort viewPort = new ViewPort(-100,100,-100,100);
	static TextGraphBuilder builder = new TextGraphBuilder();
	static Graph<String,Object> graph = buildGraph();
	static GeoPainter textPainter = new GeoPainter(5);
	static GraphPainter<String,Object> painter = new GraphPainter<String,Object>(viewPort, textPainter, textPainter);
	private Canvas canvas;
//	private AutoLayout autoLayout = new AutoLayout();
//	private ShakeLayout shakeLayout = new ShakeLayout();
//	private CenterLayout centerLayout = new CenterLayout();
//	private graph.layout.GridLayout gridLayout = new graph.layout.GridLayout();
//	private FlattenLayout flattenLayout = new FlattenLayout();
	
	public void createPartControl(Composite parent) {
		Image image = new Image (parent.getDisplay(), 16, 16);
		Color color = parent.getDisplay().getSystemColor (SWT.COLOR_RED);
		GC gc = new GC (image);
		gc.setBackground (color);
		gc.fillRectangle (image.getBounds ());
		gc.dispose ();

		Composite top = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		top.setLayout(layout);
		// top banner
		Composite banner = new Composite(top, SWT.NONE);
		banner.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL, GridData.VERTICAL_ALIGN_BEGINNING, true, false));
		layout = new GridLayout();
		layout.marginHeight = 5;
		layout.marginWidth = 10;
		layout.numColumns = 2;
		banner.setLayout(layout);
		
		makeToolbar(banner, image);
		
		canvas = new Canvas(top, SWT.NONE); //_BACKGROUND);
//		| SWT.V_SCROLL | SWT.H_SCROLL);
		canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
		canvas.addPaintListener(new PaintListener() {
			
			@Override
			public void paintControl(PaintEvent e) {
				Rectangle r = canvas.getBounds();
				painter.setArea(r);
				painter.paint(graph, e.gc);
//				e.gc.fillRectangle(r);
//				e.gc.drawLine(5, 5, r.width-10, r.height-10);
			}
		});
		MyMouseListener ml = new MyMouseListener();
		canvas.addMouseListener(ml);
		canvas.addMouseMoveListener(ml);
		addPopupMenu(canvas);
	}
	private void addPopupMenu(final Canvas canvas) {
		Menu menu = new Menu (canvas.getShell(), SWT.POP_UP);
		MenuItem item1 = new MenuItem (menu, SWT.PUSH);
		item1.setText ("Delete Selection");
		item1.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		MenuItem item2 = new MenuItem (menu, SWT.PUSH);
		item2.setText ("Delete Orphans");
		item2.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				HashSet<Node<String>> nodes = new HashSet<Node<String>>();
				nodes.addAll(graph.getNodes());
				for (Edge<String, Object> edge : graph.getEdges()) {
					nodes.remove(edge.a);
					nodes.remove(edge.b);
				}
				graph.getNodes().removeAll(nodes);
				canvas.redraw();
			}
		});
		MenuItem item3 = new MenuItem (menu, SWT.PUSH);
		item3.setText ("Delete Minorities");
		item2.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				
			}
		});
		MenuItem item4 = new MenuItem (menu, SWT.PUSH);
		item4.setText ("IsPlaneGraph");
		item4.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				PlaneGraphProperty p = new PlaneGraphProperty();
				boolean a = p.fulfill(graph);
				System.out.printf("Graph is %splane%n", a ? "" : "NOT ");
			}
		});
		canvas.setMenu (menu);
}
	class MyMouseListener implements MouseListener,MouseMoveListener {
		private int x,y;
		private boolean mouseDown;
		@Override
		public void mouseMove(MouseEvent e) {
			switch (mode) {
			case rotate:
				if (!mouseDown) return;
				int dx = e.x - x;
				int dy = e.y - y;
				x = e.x;
				y = e.y;
				Rotator rot = new Rotator(dx, dy);
				rot.transform(graph);
				canvas.redraw();
				break;
			}
		}

		@Override
		public void mouseDoubleClick(MouseEvent e) {
		}

		@Override
		public void mouseDown(MouseEvent e) {
			mouseDown = true;
			x = e.x; y = e.y;
		}

		@Override
		public void mouseUp(MouseEvent e) {
			mouseDown = false;
			switch (mode) {
			case addNode:
				if (x==e.x && y==e.y) {
					double[] pos = viewPort.realPos(e.x, e.y);
					Node<String> node = builder.newNode(pos[0], pos[1], 0);
					graph.getNodes().add(node);
					System.out.printf("%s%n",graph);
					canvas.redraw();
				}
				break;
			}
		}
		
	}
	enum Mode {
		select("Select"), rotate("Rotate"), addNode("Add Node"), addEdge("Add Edge");
		private String text;

		Mode(String s) {
			text = s;
		}
		@Override
		public String toString() {
			return text;
		}
	}
	enum Layout {
		auto("Auto", new AutoLayout()) , 
		zoomOut("ZoomOut", auto), 
		zoomIn("ZoomIn", auto), 
		shake("Shake", new ShakeLayout()), 
		center("Center", new CenterLayout()), 
		flatten("Flatten", new FlattenLayout()), 
		sphere2plane("Sphere2Plane", new Sphere2PlaneLayout()), 
		xy("XY", new XYLayout()), 
		grid("Grid", new graph.layout.GridLayout());

		private String text;
		private graph.layout.Layout layout;
		private Layout base = null;
		Layout(String t, graph.layout.Layout l) {
			text = t;
			layout = l;
		}
		Layout(String t, Layout base) {
			text = t;
			this.base = base;
		}
		@Override
		public String toString() {
			return text;
		}
		public graph.layout.Layout getLayout() {
			return layout==null ? base.getLayout() : layout;
		}
	}
	enum Transform {
		linMultiply("Linear Multiply", new Multiplyer(8,false)), circMultiply("Circular Multiply", new Multiplyer(8,true));
		private String text;
		private Transformer transform;

		Transform(String t, Transformer tr) {
			text = t;
			transform = tr;
		}
		@Override
		public String toString() {
			return text;
		}
		public Transformer getTransform() {
			return transform;
		}
	}
	Mode mode = Mode.select;
	private void makeToolbar(Composite banner, Image image) {
		ToolBar toolBar = new ToolBar (banner, SWT.FLAT | SWT.BORDER);
		for (final Mode m : Mode.values()) {
			ToolItem item = new ToolItem (toolBar, SWT.RADIO);
			item.setText(m.toString());
			//item.setImage (image);
			item.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					mode = m;
					System.out.printf("mode %s%n", m);
				}
			});
		}
		new ToolItem (toolBar, SWT.SEPARATOR);
		for (final Layout t : Layout.values()) {
			ToolItem item = new ToolItem (toolBar, SWT.PUSH);
			item.setText(t.toString());
			//item.setImage (image);
			item.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					System.out.printf("layout %s%n", t);
					switch (t) {
					case zoomIn: ((AutoLayout)t.getLayout()).zoomIn(); break;
					case zoomOut: ((AutoLayout)t.getLayout()).zoomOut(); break;
					}
					t.getLayout().layout(graph, viewPort);
					canvas.redraw();
				}
			});
		}
		new ToolItem (toolBar, SWT.SEPARATOR);
		for (final Transform t : Transform.values()) {
			ToolItem item = new ToolItem (toolBar, SWT.PUSH);
			item.setText(t.toString());
			//item.setImage (image);
			item.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					System.out.printf("layout %s%n", t);
					t.getTransform().transform(graph);
					canvas.redraw();
				}
			});
		}
		toolBar.pack ();
	}

	static Graph<String,Object>  buildGraph() {
		Graph<String,Object> graph = builder.build(graphs[index]);
		RandomLayout rl = new RandomLayout();
		rl.layout(graph, viewPort);
		return graph;
	}


	public void setFocus() {
	}
}
